use alexandria_bytes::byte_array_ext::ByteArrayTraitExt;
use zkgm::types::{
    Batch, BatchAck, Forward, Instruction, Opcode, SolverMetadata, TokenOrderAck, TokenOrderV2,
    Version, ZkgmPacket, ethabi_decode, ethabi_encode,
};

#[test]
fn test_instruction_encode_decode() {
    let mut encoded: ByteArray = Default::default();

    encoded.append_u256(0x0000000000000000000000000000000000000000000000000000000000000002);
    encoded.append_u256(0x0000000000000000000000000000000000000000000000000000000000000003);
    encoded.append_u256(0x0000000000000000000000000000000000000000000000000000000000000060);
    encoded.append_u256(0x0000000000000000000000000000000000000000000000000000000000000008);
    encoded.append_u256(0x4141414141414141000000000000000000000000000000000000000000000000);

    let instruction: Instruction = ethabi_decode(encoded.clone()).unwrap();

    let i = Instruction { version: Version::V2, opcode: Opcode::TokenOrder, operand: "AAAAAAAA" };

    assert!(i == instruction);
    assert!(ethabi_encode(@i) == encoded);
}

#[test]
fn test_zkgm_packet_encode_decode() {
    let mut encoded: ByteArray = Default::default();

    encoded.append_u256(0x4141414141414141414141414141414141414141414141414141414141414141);
    encoded.append_u256(0x0000000000000000000000000000000000000000000000000000000000000064);
    encoded.append_u256(0x0000000000000000000000000000000000000000000000000000000000000060);
    encoded.append_u256(0x0000000000000000000000000000000000000000000000000000000000000002);
    encoded.append_u256(0x0000000000000000000000000000000000000000000000000000000000000003);
    encoded.append_u256(0x0000000000000000000000000000000000000000000000000000000000000060);
    encoded.append_u256(0x0000000000000000000000000000000000000000000000000000000000000008);
    encoded.append_u256(0x4141414141414141000000000000000000000000000000000000000000000000);

    let packet: ZkgmPacket = ethabi_decode(encoded.clone()).unwrap();

    let p = ZkgmPacket {
        salt: "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
        path: 100,
        instruction: Instruction {
            version: Version::V2, opcode: Opcode::TokenOrder, operand: "AAAAAAAA",
        },
    };
    assert!(packet == p);
    assert!(encoded == ethabi_encode(@p));
}

#[test]
fn test_forward_encode_decode() {
    let mut encoded: ByteArray = Default::default();

    encoded.append_u256(0x0000000000000000000000000000000000000000000000000000000000000064);
    encoded.append_u256(0x0000000000000000000000000000000000000000000000000000000000000000);
    encoded.append_u256(0x00000000000000000000000000000000000000000000000000000000000186a0);
    encoded.append_u256(0x0000000000000000000000000000000000000000000000000000000000000080);
    encoded.append_u256(0x0000000000000000000000000000000000000000000000000000000000000002);
    encoded.append_u256(0x0000000000000000000000000000000000000000000000000000000000000003);
    encoded.append_u256(0x0000000000000000000000000000000000000000000000000000000000000060);
    encoded.append_u256(0x0000000000000000000000000000000000000000000000000000000000000008);
    encoded.append_u256(0x4141414141414141000000000000000000000000000000000000000000000000);

    let forward: Forward = ethabi_decode(encoded.clone()).unwrap();

    let f = Forward {
        path: 100,
        timeout_height: 0,
        timeout_timestamp: 100000,
        instruction: Instruction {
            version: Version::V2, opcode: Opcode::TokenOrder, operand: "AAAAAAAA",
        },
    };
    assert!(forward == f);
    assert!(encoded == ethabi_encode(@forward));
}

// #[test]
// fn test_batch_encode_decode() {
//     let mut encoded: ByteArray = Default::default();

//     encoded.append_u256(0x0000000000000000000000000000000000000000000000000000000000000020);
//     encoded.append_u256(0x0000000000000000000000000000000000000000000000000000000000000003);
//     encoded.append_u256(0x0000000000000000000000000000000000000000000000000000000000000060);
//     encoded.append_u256(0x0000000000000000000000000000000000000000000000000000000000000160);
//     encoded.append_u256(0x0000000000000000000000000000000000000000000000000000000000000220);
//     encoded.append_u256(0x0000000000000000000000000000000000000000000000000000000000000000);
//     encoded.append_u256(0x0000000000000000000000000000000000000000000000000000000000000000);
//     encoded.append_u256(0x0000000000000000000000000000000000000000000000000000000000000060);
//     encoded.append_u256(0x0000000000000000000000000000000000000000000000000000000000000079);
//     encoded.append_u256(0x68656c6c6f20776f726c6468656c6c6f20776f726c6468656c6c6f20776f726c);
//     encoded.append_u256(0x6468656c6c6f20776f726c6468656c6c6f20776f726c6468656c6c6f20776f72);
//     encoded.append_u256(0x6c6468656c6c6f20776f726c6468656c6c6f20776f726c6468656c6c6f20776f);
//     encoded.append_u256(0x726c6468656c6c6f20776f726c6468656c6c6f20776f726c6400000000000000);
//     encoded.append_u256(0x0000000000000000000000000000000000000000000000000000000000000001);
//     encoded.append_u256(0x0000000000000000000000000000000000000000000000000000000000000001);
//     encoded.append_u256(0x0000000000000000000000000000000000000000000000000000000000000060);
//     encoded.append_u256(0x0000000000000000000000000000000000000000000000000000000000000026);
//     encoded.append_u256(0x68686820776f726c6468656c6c6f20777777776c6f20776f726c6468656c6c6f);
//     encoded.append_u256(0x20776f726c640000000000000000000000000000000000000000000000000000);
//     encoded.append_u256(0x0000000000000000000000000000000000000000000000000000000000000002);
//     encoded.append_u256(0x0000000000000000000000000000000000000000000000000000000000000002);
//     encoded.append_u256(0x0000000000000000000000000000000000000000000000000000000000000060);
//     encoded.append_u256(0x0000000000000000000000000000000000000000000000000000000000000008);
//     encoded.append_u256(0x6272726168686868000000000000000000000000000000000000000000000000);

//     let batch: Batch = ethabi_decode(encoded.clone()).unwrap();

//     let b = Batch {
//         instructions: array![
//             Instruction {
//                 version: Version::V0,
//                 opcode: Opcode::Forward,
//                 operand: "hello worldhello worldhello worldhello worldhello worldhello worldhello
//                 worldhello worldhello worldhello worldhello world",
//             },
//             Instruction {
//                 version: Version::V1,
//                 opcode: Opcode::Call,
//                 operand: "hhh worldhello wwwwlo worldhello world",
//             },
//             Instruction { version: Version::V2, opcode: Opcode::Batch, operand: "brrahhhh" },
//         ],
//     };

//     assert!(batch == b);
//     assert!(encoded == ethabi_encode(@batch));
// }

#[test]
fn test_token_order_ack_encode_decode() {
    let mut encoded: ByteArray = Default::default();
    encoded.append_u256(0x00000000000000000000000000000000000000000000000000000000001e8480);
    encoded.append_u256(0x0000000000000000000000000000000000000000000000000000000000000040);
    encoded.append_u256(0x0000000000000000000000000000000000000000000000000000000000000067);
    encoded.append_u256(0x61736466736e6564666c6561736e64666c656e6173646c66656e6173656c646e);
    encoded.append_u256(0x6c6561736e64666c65616e7364666c656e6173646c65666e616c73656e64666c);
    encoded.append_u256(0x656e61736466656c6e61736c6564666c6561736e64666c656e61736c6465666e);
    encoded.append_u256(0x6c65616e73646600000000000000000000000000000000000000000000000000);

    let ack = TokenOrderAck {
        fill_type: 2000000,
        market_maker: "asdfsnedfleasndflenasdlfenaseldnleasndfleansdflenasdlefnalsendflenasdfelnasledfleasndflenasldefnleansdf",
    };

    assert!(ethabi_encode(@ack) == encoded);
    assert!(ack == ethabi_decode(encoded).unwrap());
}

#[test]
fn test_batch_ack_encode_decode() {
    let mut encoded: ByteArray = Default::default();
    encoded.append_u256(0x0000000000000000000000000000000000000000000000000000000000000020);
    encoded.append_u256(0x0000000000000000000000000000000000000000000000000000000000000003);
    encoded.append_u256(0x0000000000000000000000000000000000000000000000000000000000000060);
    encoded.append_u256(0x00000000000000000000000000000000000000000000000000000000000000a0);
    encoded.append_u256(0x00000000000000000000000000000000000000000000000000000000000000e0);
    encoded.append_u256(0x0000000000000000000000000000000000000000000000000000000000000005);
    encoded.append_u256(0x68656c6c6f000000000000000000000000000000000000000000000000000000);
    encoded.append_u256(0x0000000000000000000000000000000000000000000000000000000000000002);
    encoded.append_u256(0x6869000000000000000000000000000000000000000000000000000000000000);
    encoded.append_u256(0x0000000000000000000000000000000000000000000000000000000000000004);
    encoded.append_u256(0x6865686500000000000000000000000000000000000000000000000000000000);

    let batch_ack = BatchAck { acknowledgements: array!["hello", "hi", "hehe"] };

    assert!(ethabi_encode(@batch_ack) == encoded);
    assert!(batch_ack == ethabi_decode(encoded).unwrap());
}

#[test]
fn test_solver_metadata_encode_decode() {
    let mut encoded: ByteArray = Default::default();

    encoded.append_u256(0x0000000000000000000000000000000000000000000000000000000000000040);
    encoded.append_u256(0x0000000000000000000000000000000000000000000000000000000000000080);
    encoded.append_u256(0x0000000000000000000000000000000000000000000000000000000000000004);
    encoded.append_u256(0x4141414100000000000000000000000000000000000000000000000000000000);
    encoded.append_u256(0x0000000000000000000000000000000000000000000000000000000000000020);
    encoded.append_u256(0x4242424242424242424242424242424242424242424242424242424242424242);

    let solver_metadata = SolverMetadata {
        solver_address: "AAAA", metadata: "BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB",
    };

    assert!(ethabi_encode(@solver_metadata) == encoded);
    assert!(solver_metadata == ethabi_decode(encoded).unwrap());
}

#[test]
fn test_token_order_v2_encode_decode() {
    let mut encoded: ByteArray = Default::default();

    encoded.append_u256(0x0000000000000000000000000000000000000000000000000000000000000100);
    encoded.append_u256(0x0000000000000000000000000000000000000000000000000000000000000140);
    encoded.append_u256(0x0000000000000000000000000000000000000000000000000000000000000180);
    encoded.append_u256(0x0000000000000000000000000000000000000000000000000000000000000064);
    encoded.append_u256(0x00000000000000000000000000000000000000000000000000000000000001c0);
    encoded.append_u256(0x00000000000000000000000000000000000000000000000000000000000000fa);
    encoded.append_u256(0x0000000000000000000000000000000000000000000000000000000000000001);
    encoded.append_u256(0x0000000000000000000000000000000000000000000000000000000000000200);
    encoded.append_u256(0x0000000000000000000000000000000000000000000000000000000000000002);
    encoded.append_u256(0xabcd000000000000000000000000000000000000000000000000000000000000);
    encoded.append_u256(0x0000000000000000000000000000000000000000000000000000000000000003);
    encoded.append_u256(0x1111110000000000000000000000000000000000000000000000000000000000);
    encoded.append_u256(0x0000000000000000000000000000000000000000000000000000000000000003);
    encoded.append_u256(0x2222220000000000000000000000000000000000000000000000000000000000);
    encoded.append_u256(0x0000000000000000000000000000000000000000000000000000000000000003);
    encoded.append_u256(0x4444440000000000000000000000000000000000000000000000000000000000);
    encoded.append_u256(0x0000000000000000000000000000000000000000000000000000000000000080);
    encoded.append_u256(0x0000000000000000000000000000000000000000000000000000000000000040);
    encoded.append_u256(0x0000000000000000000000000000000000000000000000000000000000000000);
    encoded.append_u256(0x0000000000000000000000000000000000000000000000000000000000000020);
    encoded.append_u256(0xdafe631cbe5cf0e5dfb68f6b5f6ed2ebaa139a6807b47c9402d7bce691ee732d);

    let mut metadata: ByteArray = Default::default();
    metadata.append_u256(0x0000000000000000000000000000000000000000000000000000000000000040);
    metadata.append_u256(0x0000000000000000000000000000000000000000000000000000000000000000);
    metadata.append_u256(0x0000000000000000000000000000000000000000000000000000000000000020);
    metadata.append_u256(0xdafe631cbe5cf0e5dfb68f6b5f6ed2ebaa139a6807b47c9402d7bce691ee732d);

    let mut sender = Default::default();
    sender.append_u16(0xabcd);

    let mut receiver = Default::default();
    receiver.append_u16(0x1111);
    receiver.append_u8(0x11);

    let mut base_token = Default::default();
    base_token.append_u16(0x2222);
    base_token.append_u8(0x22);

    let mut quote_token = Default::default();
    quote_token.append_u16(0x4444);
    quote_token.append_u8(0x44);

    let token_order = TokenOrderV2 {
        sender,
        receiver,
        base_token,
        base_amount: 100,
        quote_token,
        quote_amount: 250,
        kind: 1,
        metadata,
    };

    assert!(ethabi_encode(@token_order) == encoded);
    assert!(token_order == ethabi_decode(encoded).unwrap());
}
